﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YRevitJig;

namespace HYRElectric.Equipment
{
	internal class LayoutEquipmentJig : XUiJigBase
	{
		public XYZ StartPoint { get; set; }

		public XYZ EndPoint { get; set; }

		private LayoutEquipmentJig.ELayoutType LayoutType { get; set; }

        public LayoutEquipmentJig(UIDocument uiDoc, System.Windows.Forms.Form formLayout)
            : base(uiDoc)
		{
			this.m_formLayout = formLayout;
		}

		public XYZ PickEndPoint(XYZ ptStart, LayoutEquipmentJig.ELayoutType layType, string strPrompt = "请确定下一点：")
		{
			try
			{
				this.LayoutType = layType;
				this.StartPoint = ptStart;
				this.EndPoint = base.UiDoc.Selection.PickPoint(strPrompt);
				if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eLine || this.LayoutType == LayoutEquipmentJig.ELayoutType.eLineExt)
				{
					XYZ axisPoint = JigFuncs.GetAxisPoint(base.UiDoc, this.EndPoint, this.StartPoint);
					if (axisPoint != null)
					{
						this.EndPoint = axisPoint;
					}
				}
			}
			catch
			{
				this.m_ptCur = System.Drawing.Point.Empty;
				return null;
			}
			this.m_ptCur = System.Drawing.Point.Empty;
			return this.EndPoint;
		}

		public override void Draw(PaintEventArgs paintEvent)
		{
			base.Draw(paintEvent);
			if (this.m_ptCur.IsEmpty)
			{
				return;
			}
			XYZ xyz = base.Client2Revit(this.m_ptCur);
			XYZ xyz2 = new XYZ(xyz.X, xyz.Y, this.StartPoint.Z);
			if (xyz2.DistanceTo(this.StartPoint) < AssistFunc.mmToFeet(10.0))
			{
				return;
			}
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eLine || this.LayoutType == LayoutEquipmentJig.ELayoutType.eLineExt)
			{
				XYZ axisPoint = JigFuncs.GetAxisPoint(base.UiDoc, xyz2, this.StartPoint);
				if (axisPoint != null)
				{
					xyz2 = new XYZ(axisPoint.X, axisPoint.Y, this.StartPoint.Z);
					this.m_ptCur = base.Revit2Client(xyz2);
					base.DrawAxisLine(paintEvent.Graphics, this.StartPoint, xyz2);
				}
			}
			this.m_dEquipSize = AssistFunc.mmToFeet(6.0) * (double)base.UiDoc.ActiveView.Scale;
			Graphics graphics = paintEvent.Graphics;
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eLine)
			{
				this.DrawLineLayout(this.StartPoint, xyz2, graphics);
				return;
			}
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eLineExt)
			{
				this.DrawLineExtLayout(this.StartPoint, xyz2, graphics);
				return;
			}
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eRect)
			{
				this.DrawRectLayout(this.StartPoint, xyz2, graphics);
				return;
			}
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eRectEx)
			{
				this.DrawRectExtLayout(this.StartPoint, xyz2, graphics);
				return;
			}
			if (this.LayoutType == LayoutEquipmentJig.ELayoutType.eFireRect)
			{
				this.DrawFireRectLayout(this.StartPoint, xyz2, graphics);
			}
		}

		private void DrawLineLayout(XYZ ptStart, XYZ ptEnd, Graphics drawGraphics)
		{
			DragLineLayoutForm dragLineLayoutForm = this.m_formLayout as DragLineLayoutForm;
			if (dragLineLayoutForm == null)
			{
				return;
			}
			dragLineLayoutForm.UpdateData();
			XYZ xyz = (ptEnd - ptStart).Normalize();
			if (!dragLineLayoutForm.IsAutoAngle)
			{
				xyz = Transform.CreateRotation(XYZ.BasisZ, (double)dragLineLayoutForm.Angle / 180.0 * Math.PI).OfVector(XYZ.BasisX);
			}
			List<XYZ> list = this.LineLayoutEquipPos(ptStart, ptEnd);
			XGraphics xgraphics = new XGraphics(drawGraphics, base.JigPen);
			foreach (XYZ ptPos in list)
			{
				this.DrawEquipAsCross(ptPos, xyz, xgraphics);
			}
			XYZ xyz2 = (ptEnd - ptStart).Normalize();
			if (xyz2.IsAlmostEqualTo(xyz, 0.001))
			{
				XYZ point = ptStart;
				foreach (XYZ xyz3 in list)
				{
					XYZ point2 = xyz3 - xyz2 * 0.5 * this.m_dEquipSize;
					new XLine2D(base.Revit2Client(point), base.Revit2Client(point2)).Draw(xgraphics);
					point = xyz3 + xyz2 * 0.5 * this.m_dEquipSize;
				}
				new XLine2D(base.Revit2Client(point), base.Revit2Client(ptEnd)).Draw(xgraphics);
				return;
			}
			new XLine2D(base.Revit2Client(ptStart), base.Revit2Client(ptEnd)).Draw(xgraphics);
		}

		private void DrawLineExtLayout(XYZ ptStart, XYZ ptEnd, Graphics drawGraphics)
		{
			DragLineExLayoutForm dragLineExLayoutForm = this.m_formLayout as DragLineExLayoutForm;
			if (dragLineExLayoutForm == null)
			{
				return;
			}
			dragLineExLayoutForm.UpdateData();
			XYZ xyz = (ptEnd - ptStart).Normalize();
			if (!dragLineExLayoutForm.IsAutoAngle)
			{
				xyz = Transform.CreateRotation(XYZ.BasisZ, (double)dragLineExLayoutForm.Angle / 180.0 * Math.PI).OfVector(XYZ.BasisX);
			}
			List<XYZ> list = this.LineExtLayoutEquipPos(ptStart, ptEnd);
			XGraphics xgraphics = new XGraphics(drawGraphics, base.JigPen);
			foreach (XYZ ptPos in list)
			{
				this.DrawEquipAsCross(ptPos, xyz, xgraphics);
			}
			XYZ xyz2 = (ptEnd - ptStart).Normalize();
			if (xyz2.IsAlmostEqualTo(xyz, 0.001))
			{
				XYZ point = ptStart;
				foreach (XYZ xyz3 in list)
				{
					XYZ point2 = xyz3 - xyz2 * 0.5 * this.m_dEquipSize;
					new XLine2D(base.Revit2Client(point), base.Revit2Client(point2)).Draw(xgraphics);
					point = xyz3 + xyz2 * 0.5 * this.m_dEquipSize;
				}
				new XLine2D(base.Revit2Client(point), base.Revit2Client(ptEnd)).Draw(xgraphics);
				return;
			}
			new XLine2D(base.Revit2Client(ptStart), base.Revit2Client(ptEnd)).Draw(xgraphics);
		}

		private void DrawRectLayout(XYZ ptStart, XYZ ptEnd, Graphics drawGraphics)
		{
			RectLayoutForm rectLayoutForm = this.m_formLayout as RectLayoutForm;
			if (rectLayoutForm == null)
			{
				return;
			}
			rectLayoutForm.UpdateData();
			XYZ vtEquip = Transform.CreateRotation(XYZ.BasisZ, (double)rectLayoutForm.Angle / 180.0 * Math.PI).OfVector(XYZ.BasisX);
			List<XYZ> list = this.RectLayoutEquipPos(ptStart, ptEnd);
			XGraphics graphics = new XGraphics(drawGraphics, base.JigPen);
			foreach (XYZ ptPos in list)
			{
				this.DrawEquipAsCross(ptPos, vtEquip, graphics);
			}
			double dRectAngle = (double)rectLayoutForm.RowAngle / 180.0 * Math.PI;
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(dRectAngle, ptStart, ptEnd, ref zero, ref zero2);
			this.DrawRectangle(zero, ptStart, ptEnd, zero2, graphics);
		}

		private void DrawRectExtLayout(XYZ ptStart, XYZ ptEnd, Graphics drawGraphics)
		{
			RectLayoutExForm rectLayoutExForm = this.m_formLayout as RectLayoutExForm;
			if (rectLayoutExForm == null)
			{
				return;
			}
			rectLayoutExForm.UpdateData();
			XYZ vtEquip = Transform.CreateRotation(XYZ.BasisZ, (double)rectLayoutExForm.Angle / 180.0 * Math.PI).OfVector(XYZ.BasisX);
			List<XYZ> list = this.RectExtLayoutEquipPos(ptStart, ptEnd);
			XGraphics graphics = new XGraphics(drawGraphics, base.JigPen);
			foreach (XYZ ptPos in list)
			{
				this.DrawEquipAsCross(ptPos, vtEquip, graphics);
			}
			double dRectAngle = (double)rectLayoutExForm.RowAngle / 180.0 * Math.PI;
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(dRectAngle, ptStart, ptEnd, ref zero, ref zero2);
			this.DrawRectangle(zero, ptStart, ptEnd, zero2, graphics);
		}

		private void DrawFireRectLayout(XYZ ptStart, XYZ ptEnd, Graphics drawGraphics)
		{
			if (!(this.m_formLayout is FireRectLayoutForm))
			{
				return;
			}
			List<XYZ> list = this.FireRectLayoutEquipPos(ptStart, ptEnd);
			XGraphics graphics = new XGraphics(drawGraphics, base.JigPen);
			foreach (XYZ ptPos in list)
			{
				this.DrawEquipAsCross(ptPos, XYZ.BasisX, graphics);
			}
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(0.0, ptStart, ptEnd, ref zero, ref zero2);
			this.DrawRectangle(zero, ptStart, ptEnd, zero2, graphics);
		}

		private List<XYZ> LineLayoutEquipPos(XYZ ptStart, XYZ ptEnd)
		{
			List<XYZ> list = new List<XYZ>();
			if (ptStart.DistanceTo(ptEnd) < AssistFunc.mmToFeet(1.5))
			{
				return list;
			}
			DragLineLayoutForm dragLineLayoutForm = this.m_formLayout as DragLineLayoutForm;
			double num = AssistFunc.mmToFeet((double)dragLineLayoutForm.Space);
			XYZ xyz = (ptEnd - ptStart).Normalize();
			if (dragLineLayoutForm.AlignWay == 0)
			{
				double num2 = AssistFunc.mmToFeet((double)dragLineLayoutForm.SpaceToStart);
				XYZ xyz2 = ptStart + xyz * num2;
				XYZ xyz3 = (ptEnd - xyz2).Normalize();
				while (xyz3.IsAlmostEqualTo(xyz, 0.1))
				{
					list.Add(xyz2);
					xyz2 += xyz * num;
					xyz3 = (ptEnd - xyz2).Normalize();
				}
			}
			else
			{
				XYZ xyz4 = ptStart + (ptEnd - ptStart) / 2.0;
				XYZ xyz5 = -xyz;
				XYZ xyz6 = xyz4 + xyz5 * num;
				XYZ xyz7 = (ptStart - xyz6).Normalize();
				List<XYZ> list2 = new List<XYZ>();
				while (xyz7.IsAlmostEqualTo(xyz5, 0.1))
				{
					list2.Add(xyz6);
					xyz6 += xyz5 * num;
					xyz7 = (ptStart - xyz6).Normalize();
				}
				list2.Reverse();
				list.AddRange(list2);
				list.Add(xyz4);
				xyz6 = xyz4 + xyz * num;
				xyz7 = (ptEnd - xyz6).Normalize();
				while (xyz7.IsAlmostEqualTo(xyz, 0.1))
				{
					list.Add(xyz6);
					xyz6 += xyz * num;
					xyz7 = (ptEnd - xyz6).Normalize();
				}
			}
			return list;
		}

		private List<XYZ> LineExtLayoutEquipPos(XYZ ptStart, XYZ ptEnd)
		{
			List<XYZ> list = new List<XYZ>();
			double num = ptStart.DistanceTo(ptEnd);
			if (num < AssistFunc.mmToFeet(1.5))
			{
				return list;
			}
			DragLineExLayoutForm dragLineExLayoutForm = this.m_formLayout as DragLineExLayoutForm;
			double num2 = num / ((double)(dragLineExLayoutForm.Count - 1) + 2.0 * dragLineExLayoutForm.Margin);
			XYZ xyz = (ptEnd - ptStart).Normalize();
			XYZ xyz2 = ptStart + xyz * dragLineExLayoutForm.Margin * num2;
			list.Add(xyz2);
			for (int i = 1; i < dragLineExLayoutForm.Count; i++)
			{
				xyz2 += xyz * num2;
				list.Add(xyz2);
			}
			return list;
		}

		private List<XYZ> RectLayoutEquipPos(XYZ ptLeftTop, XYZ ptRightBottom)
		{
			List<XYZ> list = new List<XYZ>();
			RectLayoutForm rectLayoutForm = this.m_formLayout as RectLayoutForm;
			double num = AssistFunc.mmToFeet((double)rectLayoutForm.RowSpace);
			double num2 = AssistFunc.mmToFeet((double)rectLayoutForm.ColSpace);
			double num3 = AssistFunc.mmToFeet((double)rectLayoutForm.RowMargin);
			double num4 = AssistFunc.mmToFeet((double)rectLayoutForm.ColMargin);
			double dRectAngle = (double)rectLayoutForm.RowAngle / 180.0 * Math.PI;
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(dRectAngle, ptLeftTop, ptRightBottom, ref zero, ref zero2);
			double num5 = AssistFunc.mmToFeet(1.5);
			double num6 = ptLeftTop.DistanceTo(zero2);
			double num7 = ptLeftTop.DistanceTo(zero);
			XYZ xyz = (zero2 - ptLeftTop).Normalize();
			XYZ xyz2 = (zero - ptLeftTop).Normalize();
			if (num6 < num5 || num7 < num5)
			{
				return list;
			}
			if (rectLayoutForm.DislocationWay == 0)
			{
				XYZ xyz3 = ptLeftTop + xyz2 * num3;
				XYZ xyz4 = (zero - xyz3).Normalize();
				while (xyz4.IsAlmostEqualTo(xyz2, 0.1))
				{
					XYZ xyz5 = xyz3 + xyz * num6;
					XYZ xyz6 = xyz3 + xyz * num4;
					XYZ xyz7 = (xyz5 - xyz6).Normalize();
					while (xyz7.IsAlmostEqualTo(xyz, 0.1))
					{
						list.Add(xyz6);
						xyz6 += xyz * num2;
						xyz7 = (xyz5 - xyz6).Normalize();
					}
					xyz3 += xyz2 * num;
					xyz4 = (zero - xyz3).Normalize();
				}
			}
			else if (rectLayoutForm.DislocationWay == 1)
			{
				int num8 = 0;
				XYZ xyz8 = ptLeftTop + xyz2 * num3;
				XYZ xyz9 = (zero - xyz8).Normalize();
				while (xyz9.IsAlmostEqualTo(xyz2, 0.1))
				{
					XYZ xyz10 = xyz8 + xyz * num6;
					XYZ xyz11 = xyz8 + xyz * num4;
					if (num8 % 2 != 0)
					{
						xyz11 += xyz * 0.5 * num2;
					}
					XYZ xyz12 = (xyz10 - xyz11).Normalize();
					while (xyz12.IsAlmostEqualTo(xyz, 0.1))
					{
						list.Add(xyz11);
						xyz11 += xyz * num2;
						xyz12 = (xyz10 - xyz11).Normalize();
					}
					num8++;
					xyz8 += xyz2 * num;
					xyz9 = (zero - xyz8).Normalize();
				}
			}
			else if (rectLayoutForm.DislocationWay == 2)
			{
				int num9 = 0;
				XYZ xyz13 = ptLeftTop + xyz * num4;
				XYZ xyz14 = (zero2 - xyz13).Normalize();
				while (xyz14.IsAlmostEqualTo(xyz, 0.0001))
				{
					XYZ xyz15 = xyz13 + xyz2 * num7;
					XYZ xyz16 = xyz13 + xyz2 * num3;
					if (num9 % 2 != 0)
					{
						xyz16 += xyz2 * 0.5 * num;
					}
					XYZ xyz17 = (xyz15 - xyz16).Normalize();
					while (xyz17.IsAlmostEqualTo(xyz2, 0.0001))
					{
						list.Add(xyz16);
						xyz16 += xyz2 * num;
						xyz17 = (xyz15 - xyz16).Normalize();
					}
					num9++;
					xyz13 += xyz * num2;
					xyz14 = (zero2 - xyz13).Normalize();
				}
			}
			return list;
		}

		private List<XYZ> RectExtLayoutEquipPos(XYZ ptLeftTop, XYZ ptRightBottom)
		{
			List<XYZ> list = new List<XYZ>();
			RectLayoutExForm rectLayoutExForm = this.m_formLayout as RectLayoutExForm;
			int rowCount = rectLayoutExForm.RowCount;
			int colCount = rectLayoutExForm.ColCount;
			double margin = rectLayoutExForm.Margin;
			double dRectAngle = (double)rectLayoutExForm.RowAngle / 180.0 * Math.PI;
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(dRectAngle, ptLeftTop, ptRightBottom, ref zero, ref zero2);
			double num = AssistFunc.mmToFeet(1.5);
			double num2 = ptLeftTop.DistanceTo(zero2);
			double num3 = ptLeftTop.DistanceTo(zero);
			XYZ xyz = (zero2 - ptLeftTop).Normalize();
			XYZ xyz2 = (zero - ptLeftTop).Normalize();
			if (num2 < num || num3 < num)
			{
				return list;
			}
			double num4 = num3 / ((double)(rowCount - 1) + 2.0 * margin);
			double num5 = num2 / ((double)(colCount - 1) + 2.0 * margin);
			if (rectLayoutExForm.DislocationWay == 0)
			{
				XYZ xyz3 = ptLeftTop + xyz2 * margin * num4;
				for (int i = 0; i < rowCount; i++)
				{
					XYZ xyz4 = xyz3 + xyz * margin * num5;
					for (int j = 0; j < colCount; j++)
					{
						list.Add(xyz4);
						xyz4 += xyz * num5;
					}
					xyz3 += xyz2 * num4;
				}
			}
			else if (rectLayoutExForm.DislocationWay == 1)
			{
				XYZ xyz5 = ptLeftTop + xyz2 * margin * num4;
				for (int k = 0; k < rowCount; k++)
				{
					XYZ xyz6 = xyz5 + xyz * margin * num5;
					if (k % 2 == 0)
					{
						for (int l = 0; l < colCount; l++)
						{
							list.Add(xyz6);
							xyz6 += xyz * num5;
						}
					}
					else
					{
						xyz6 += xyz * 0.5 * num5;
						for (int m = 0; m < colCount - 1; m++)
						{
							list.Add(xyz6);
							xyz6 += xyz * num5;
						}
					}
					xyz5 += xyz2 * num4;
				}
			}
			else if (rectLayoutExForm.DislocationWay == 2)
			{
				XYZ xyz7 = ptLeftTop + xyz * margin * num5;
				for (int n = 0; n < colCount; n++)
				{
					XYZ xyz8 = xyz7 + xyz2 * margin * num4;
					if (n % 2 == 0)
					{
						for (int num6 = 0; num6 < rowCount; num6++)
						{
							list.Add(xyz8);
							xyz8 += xyz2 * num4;
						}
					}
					else
					{
						xyz8 += xyz2 * 0.5 * num4;
						for (int num7 = 0; num7 < rowCount - 1; num7++)
						{
							list.Add(xyz8);
							xyz8 += xyz2 * num4;
						}
					}
					xyz7 += xyz * num5;
				}
			}
			return list;
		}

		private List<XYZ> FireRectLayoutEquipPos(XYZ ptLeftTop, XYZ ptRightBottom)
		{
			double num = Math.Abs(UnitConvert.LengthToStd((this.m_formLayout as FireRectLayoutForm).MaxSpace));
			XYZ zero = XYZ.Zero;
			XYZ zero2 = XYZ.Zero;
			this.RectCornerPoint(0.0, ptLeftTop, ptRightBottom, ref zero, ref zero2);
			double num2 = ptLeftTop.DistanceTo(zero2);
			double num3 = ptLeftTop.DistanceTo(zero);
			XYZ xyz = (zero2 - ptLeftTop).Normalize();
			XYZ xyz2 = (zero - ptLeftTop).Normalize();
			int num4;
			int num5;
			if (num > 0.0)
			{
				num4 = Convert.ToInt32(Math.Ceiling(num3 / num));
				num5 = Convert.ToInt32(Math.Ceiling(num2 / num));
			}
			else
			{
				num4 = 1;
				num5 = 1;
			}
			double num6 = 0.5;
			double num7 = num2 / (double)num5;
			double num8 = num3 / (double)num4;
			List<XYZ> list = new List<XYZ>();
			for (int i = 0; i < num4; i++)
			{
				XYZ xyz3 = ptLeftTop + xyz2 * (num6 + (double)i) * num8;
				for (int j = 0; j < num5; j++)
				{
					XYZ item = xyz3 + xyz * (num6 + (double)j) * num7;
					list.Add(item);
				}
			}
			return list;
		}

		private void DrawLine(XYZ ptStart, XYZ ptEnd, XGraphics graphics)
		{
			if (ptStart.DistanceTo(ptEnd) > AssistFunc.mmToFeet(1.0))
			{
				new XLine2D(base.Revit2Client(ptStart), base.Revit2Client(ptEnd)).Draw(graphics);
			}
		}

		private void DrawEquipAsCross(XYZ ptPos, XYZ vtEquip, XGraphics graphics)
		{
			double num = 0.5 * this.m_dEquipSize;
			XYZ ptStart = ptPos - vtEquip * num;
			XYZ ptEnd = ptPos + vtEquip * num;
			this.DrawLine(ptStart, ptEnd, graphics);
			XYZ xyz = Transform.CreateRotation(XYZ.BasisZ, Math.PI*.5).OfVector(vtEquip);
			ptStart = ptPos - xyz * num;
			ptEnd = ptPos + xyz * num;
			this.DrawLine(ptStart, ptEnd, graphics);
		}

		private void DrawRectangle(XYZ ptLB, XYZ ptLT, XYZ ptRB, XYZ ptRT, XGraphics graphics)
		{
			this.DrawLine(ptLT, ptLB, graphics);
			this.DrawLine(ptLB, ptRB, graphics);
			this.DrawLine(ptRB, ptRT, graphics);
			this.DrawLine(ptRT, ptLT, graphics);
		}

		private void RectCornerPoint(double dRectAngle, XYZ ptLT, XYZ ptRB, ref XYZ ptLB, ref XYZ ptRT)
		{
			Transform transform = Transform.CreateRotation(XYZ.BasisZ, dRectAngle);
			Transform transform2 = Transform.CreateRotation(XYZ.BasisZ, Math.PI*.5);
			XYZ xyz = transform.OfVector(XYZ.BasisX);
			XYZ xyz2 = transform2.OfVector(xyz);
			Line line = Line.CreateUnbound(ptLT, xyz);
			Line line2 = Line.CreateUnbound(ptRB, xyz2);
			ptRT = this.TwoLineIntersect(line, line2);
			Line line3 = Line.CreateUnbound(ptRB, xyz);
			Line line4 = Line.CreateUnbound(ptLT, xyz2);
			ptLB = this.TwoLineIntersect(line3, line4);
		}

		private XYZ TwoLineIntersect(Line line1, Line line2)
		{
			IntersectionResultArray intersectionResultArray = null;
			line1.Intersect(line2, out intersectionResultArray);
			if (intersectionResultArray != null && intersectionResultArray.Size > 0)
			{
				return intersectionResultArray.get_Item(0).XYZPoint;
			}
			return null;
		}

		private double m_dEquipSize;

        private System.Windows.Forms.Form m_formLayout;

		public enum ELayoutType
		{
			eLine,
			eLineExt,
			eRect,
			eRectEx,
			eFireRect
		}
	}
}
